package com.mlink.ai.chat.ui.adapter

import android.animation.AnimatorSet
import android.annotation.SuppressLint
import android.app.Activity
import android.graphics.BitmapFactory
import android.net.Uri
import android.os.Bundle
import android.text.TextUtils
import android.util.DisplayMetrics
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.core.view.isVisible
import androidx.recyclerview.widget.RecyclerView
import com.bumptech.glide.Glide
import com.google.gson.Gson
import com.mlink.ai.chat.assistant.robot.R
import com.mlink.ai.chat.assistant.robot.databinding.ItemChatAnswerBinding
import com.mlink.ai.chat.assistant.robot.databinding.ItemChatErrorBinding
import com.mlink.ai.chat.assistant.robot.databinding.ItemChatLimitsBinding
import com.mlink.ai.chat.assistant.robot.databinding.ItemChatLoadingBinding
import com.mlink.ai.chat.assistant.robot.databinding.ItemChatPhotoBinding
import com.mlink.ai.chat.assistant.robot.databinding.ItemChatQuestionBinding
import com.mlink.ai.chat.local.entity.ChatMessageEntity
import com.mlink.ai.chat.network.bean.response.GetAnswerResponse
import com.mlink.ai.chat.ui.activity.HistoryActivity
import com.mlink.ai.chat.utils.AnalyticsEvents
import com.mlink.ai.chat.utils.AnalyticsParams
import com.mlink.ai.chat.utils.AnimationUtil
import com.mlink.ai.chat.utils.LanguageUtils
import com.mlink.ai.chat.utils.dp2px
import com.mlink.ai.chat.utils.logEvent
import com.mlink.ai.chat.utils.subStringSafely
import java.io.File
import java.io.FileInputStream
import java.text.SimpleDateFormat
import java.util.Calendar
import kotlin.math.min

enum class ChatType {
    TYPE_GUIDE,
    TYPE_QUESTION,
    TYPE_ANSWER,
    TYPE_LOADING, // 暂时先保留，为了不闪烁，loading 暂时放在 answer type 里面
    TYPE_ERROR,
    TYPE_LIMITS, // 达到上限
    TYPE_PHOTO
}

data class ChatItem(
    val content: GetAnswerResponse? = null,
    val type: ChatType,
    var isLoading: Boolean = false,
    var isGood: Boolean? = null
)

class ChatRecyclerAdapter : RecyclerView.Adapter<RecyclerView.ViewHolder>() {

    var data = mutableListOf<ChatItem>()
        private set
    var listener: ChatFunctionListener? = null
    private var recyclerView: RecyclerView? = null

    private lateinit var animatorSet: AnimatorSet
    private var isFirstBindLimit = false

    private val callBack = Runnable {
        listener?.onRemoveLimitsShow(true, isShowAdLimit = false)
    }
    private val likeLoggedList = mutableListOf<ChatItem>() // 已经打过点的点赞
    private val unlikeLoggedList = mutableListOf<ChatItem>() // 已经打过点的点踩

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
        return when (viewType) {
            ChatType.TYPE_GUIDE.ordinal -> GuideViewHolder(
                ItemChatAnswerBinding.inflate(
                    LayoutInflater.from(parent.context), parent, false
                )
            )

            ChatType.TYPE_QUESTION.ordinal -> QuestionViewHolder(
                ItemChatQuestionBinding.inflate(
                    LayoutInflater.from(parent.context), parent, false
                )
            )

            ChatType.TYPE_ANSWER.ordinal -> AnswerViewHolder(
                ItemChatAnswerBinding.inflate(
                    LayoutInflater.from(parent.context), parent, false
                )
            )

            ChatType.TYPE_LOADING.ordinal -> LoadingViewHolder(
                ItemChatLoadingBinding.inflate(
                    LayoutInflater.from(parent.context), parent, false
                )
            )

            ChatType.TYPE_ERROR.ordinal -> ErrorViewHolder(
                ItemChatErrorBinding.inflate(
                    LayoutInflater.from(parent.context), parent, false
                )
            )

            ChatType.TYPE_LIMITS.ordinal -> LimitsViewHolder(
                ItemChatLimitsBinding.inflate(
                    LayoutInflater.from(parent.context), parent, false
                )
            )

            ChatType.TYPE_PHOTO.ordinal -> PhotoViewHolder(
                ItemChatPhotoBinding.inflate(
                    LayoutInflater.from(parent.context), parent, false
                )
            )

            else -> ErrorViewHolder(
                ItemChatErrorBinding.inflate(
                    LayoutInflater.from(parent.context), parent, false
                )
            )
        }
    }


    override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
        val item = data[position]
        when (holder) {
            is GuideViewHolder -> bindGuideViewHolder(holder, item)
            is QuestionViewHolder -> bindQuestionViewHolder(holder, item)
            is AnswerViewHolder -> bindAnswerViewHolder(holder, item)
            is LoadingViewHolder -> bindLoadingViewHolder(holder, item)
            is ErrorViewHolder -> bindErrorViewHolder(holder, item)
            is LimitsViewHolder -> bindLimitsViewHolder(holder, item)
            is PhotoViewHolder -> bindPhotoViewHolder(holder, item)
        }
    }

    override fun onBindViewHolder(
        holder: RecyclerView.ViewHolder,
        position: Int,
        payloads: MutableList<Any>
    ) {
        if (payloads.isEmpty()) {
            super.onBindViewHolder(holder, position, payloads)
            return
        }
        if (holder is AnswerViewHolder) {
            bindAnswerViewHolder(holder, data[position], payloads)
        }
        if (holder is LimitsViewHolder) {
            bindLimitsViewHolder(holder, data[position], payloads)
        }
    }

    override fun onAttachedToRecyclerView(recyclerView: RecyclerView) {
        this.recyclerView = recyclerView
        super.onAttachedToRecyclerView(recyclerView)
    }

    @SuppressLint("NotifyDataSetChanged")
    fun replaceMessageList(itemList: List<ChatItem>) {
        data.clear()
        data.addAll(itemList)
        notifyDataSetChanged()
    }

    fun addMessage(item: ChatItem) {
        listener?.onRegenerateVisible(item.type == ChatType.TYPE_ERROR)
        // 达到每日上限的场景
        if (item.type == ChatType.TYPE_LIMITS && data.last().type == ChatType.TYPE_ANSWER && data.last().isLoading) {
            data.removeLast()
            listener?.onGoingToBilling()
            recyclerView?.removeCallbacks(callBack)
            recyclerView?.postDelayed(callBack, 1500L)
            data.add(item)
            isFirstBindLimit = true
            notifyItemChanged(data.size - 1)
            scrollToBottom()
            ChatMessageEntity.saveTempData(getHistoryEntity())
            return
        }
        // 点击 regenerate 的场景
        if (data.isNotEmpty() && data.last().type == ChatType.TYPE_ERROR && item.isLoading) {
            data.removeLast()
            data.add(item)
            notifyItemChanged(data.size - 1)
            scrollToBottom()
            ChatMessageEntity.saveTempData(getHistoryEntity())
            return
        }
        // answer 去覆盖 loading 的场景
        if (data.isNotEmpty() && data.last().type == ChatType.TYPE_ANSWER && data.last().isLoading) {
            data.removeLast()
            data.add(item)
            notifyItemChanged(data.size - 1, Bundle().apply { putBoolean(KEY_IS_LOADING, false) })
            scrollToBottom()
            ChatMessageEntity.saveTempData(getHistoryEntity())
            return
        }
        data.add(item)
        notifyItemInserted(data.size - 1)
        scrollToBottom()
        ChatMessageEntity.saveTempData(getHistoryEntity())
        ChatMessageEntity.saveTempPic(getAllPic())
    }

    fun getLastConversationId(): String? {
        val item = data.findLast {
            it.content?.conversationId != null
        }
        return item?.content?.conversationId
    }

    fun getLastPhotoPath(): String? {
        val item = data.findLast {
            it.type == ChatType.TYPE_PHOTO || it.type == ChatType.TYPE_QUESTION
        }
        item ?: return null
        return if (item.type == ChatType.TYPE_PHOTO) {
            item.content?.imagePath
        } else {
            null
        }
    }

    fun getLastQuestionContent(): String? {
        val item = data.findLast {
            it.type == ChatType.TYPE_QUESTION || it.type == ChatType.TYPE_PHOTO
        }
        return item?.content?.answer
    }

    fun isQuestionEmpty(): Boolean {
        val item = data.find {
            it.type == ChatType.TYPE_ANSWER && !it.isLoading
        }
        return item == null
    }

    fun isLimitsEmpty(): Boolean {
        val item = data.find {
            it.type == ChatType.TYPE_LIMITS
        }
        return item == null
    }

    @SuppressLint("NotifyDataSetChanged")
    fun removeAllLimits() {
        data.forEach {
            if (it.type == ChatType.TYPE_LIMITS) {
                data.remove(it)
            }
        }
        if (this::animatorSet.isInitialized) {
            animatorSet.cancel()
        }
        notifyDataSetChanged()
    }

    fun notifyLimitsItemChanged(showAdLimits: Boolean, isLoading: Boolean) {
        val item = data.findLast {
            it.type == ChatType.TYPE_LIMITS
        }
        if (item != null && data.indexOf(item) != -1) {
            item.isLoading = isLoading
            val bundle = Bundle().apply {
                putBoolean(KEY_IS_LOADING, isLoading)
                putBoolean(KEY_IS_SHOW_AD_LIMITS, showAdLimits)
            }
            notifyItemChanged(data.indexOf(item), bundle)
        }
    }

    fun isLastAnswerIsLimits(): Boolean {
        return data.isNotEmpty() && data.last().type == ChatType.TYPE_LIMITS
    }

    fun scrollToBottom() {
        recyclerView?.postDelayed({
            if (data.size == 0) {
                return@postDelayed
            }
            recyclerView?.smoothScrollToPosition(data.size - 1)
        }, 300L)
    }

    fun getHistoryEntity(): ChatMessageEntity? {
        val firstQuestion =
            data.find { it.type == ChatType.TYPE_QUESTION || it.type == ChatType.TYPE_PHOTO }
                ?: return null
        if (data.find { it.type == ChatType.TYPE_ANSWER && !it.isLoading } == null) return null
        val historyList = data.filter {
            it.type == ChatType.TYPE_QUESTION || (it.type == ChatType.TYPE_ANSWER && !it.isLoading) || it.type == ChatType.TYPE_PHOTO
        }
        var title = ""
        firstQuestion.content?.answer?.let { title = it.substring(0, min(it.length, 27)) }
        val cal = Calendar.getInstance()
        val dataFormat = SimpleDateFormat("MM/dd/yyyy hh:mm a", LanguageUtils.getCurrentLocale())
        val date = dataFormat.format(cal.time)
        return ChatMessageEntity(
            messageTitle = title,
            messageContent = Gson().toJson(historyList),
            date = date
        )
    }

    fun getAllPic(): List<String> {
        val list = mutableListOf<String>()
        data.forEach {
            if (!TextUtils.isEmpty(it.content?.imagePath)) {
                list.add(it.content?.imagePath!!)
            }
        }
        return list
    }

    private fun bindGuideViewHolder(holder: GuideViewHolder, item: ChatItem) {
        holder.binding.tvContent.text = item.content?.answer
        holder.binding.llFunction.isVisible = false
        holder.binding.lavLoading.isVisible = false
    }

    private fun bindQuestionViewHolder(holder: QuestionViewHolder, item: ChatItem) {
        holder.binding.tvContent.text = item.content?.answer
        holder.binding.root.setOnLongClickListener {
            AnalyticsEvents.AC_CHATAI_COPY.logEvent(
                Bundle().apply {
                    putString(AnalyticsParams.KEY_TYPE, AnalyticsParams.ASK)
                }
            )
            listener?.onCopyContent(item)
            true
        }
    }

    private fun bindAnswerViewHolder(holder: AnswerViewHolder, item: ChatItem) {
        bindAnswerViewHolderInternal(holder, item, item.isLoading)
    }

    private fun bindAnswerViewHolder(
        holder: AnswerViewHolder,
        item: ChatItem,
        payloads: MutableList<Any>
    ) {
        val isLoading = (payloads[0] as? Bundle)?.getBoolean(KEY_IS_LOADING) ?: false
        bindAnswerViewHolderInternal(holder, item, isLoading)
    }

    private fun bindAnswerViewHolderInternal(
        holder: AnswerViewHolder,
        item: ChatItem, isLoading: Boolean
    ) {
        if (isLoading) {
            holder.binding.run {
                lavLoading.isVisible = true
                tvContent.isVisible = false
                llFunction.isVisible = false
                lavLoading.playAnimation()
            }
            return
        }
        holder.binding.run {
            lavLoading.isVisible = false
            tvContent.isVisible = true
            llFunction.isVisible = true
            if (root.context is HistoryActivity) {
                llFunction.isVisible = false
            }
            lavLoading.cancelAnimation()
            tvContent.text = item.content?.answer
            ivCopy.setOnClickListener {
                AnalyticsEvents.AC_CHATAI_COPY.logEvent(
                    Bundle().apply {
                        putString(AnalyticsParams.KEY_TYPE, AnalyticsParams.QUS)
                    }
                )
                listener?.onCopyContent(item)
            }

            ivShare.setOnClickListener {
                AnalyticsEvents.AC_CHATAI_MSG_SHARE.logEvent()
                listener?.onShareContent(item)
            }

            when (item.isGood) {
                null -> {
                    ivGood.setImageResource(R.drawable.ic_chat_good_n)
                    ivBad.setImageResource(R.drawable.ic_chat_bad_n)
                }

                true -> {
                    ivGood.setImageResource(R.drawable.ic_chat_good)
                    ivBad.setImageResource(R.drawable.ic_chat_bad_n)
                }

                false -> {
                    ivGood.setImageResource(R.drawable.ic_chat_good_n)
                    ivBad.setImageResource(R.drawable.ic_chat_bad)
                }
            }
            ivGood.setOnClickListener {
                when (item.isGood) {
                    null -> {
                        item.isGood = true
                        ivGood.setImageResource(R.drawable.ic_chat_good)
                        ivBad.setImageResource(R.drawable.ic_chat_bad_n)
                        if (!likeLoggedList.contains(item)) {
                            likeLoggedList.add(item)
                            AnalyticsEvents.AC_CHATAI_MSG_VOTE.logEvent(
                                Bundle().apply {
                                    putString(AnalyticsParams.KEY_TYPE, AnalyticsParams.LIKE)
                                    putString(
                                        AnalyticsParams.KEY_TITLE,
                                        holder.binding.root.context.subStringSafely(
                                            item.content?.answer,
                                            0,
                                            100
                                        )
                                    )
                                }
                            )
                        }
                        listener?.onClickGood(item)
                    }

                    true -> {
                        item.isGood = null
                        ivGood.setImageResource(R.drawable.ic_chat_good_n)
                        ivBad.setImageResource(R.drawable.ic_chat_bad_n)
                    }

                    false -> {
                        item.isGood = true
                        ivGood.setImageResource(R.drawable.ic_chat_good)
                        ivBad.setImageResource(R.drawable.ic_chat_bad_n)
                        if (!likeLoggedList.contains(item)) {
                            likeLoggedList.add(item)
                            AnalyticsEvents.AC_CHATAI_MSG_VOTE.logEvent(
                                Bundle().apply {
                                    putString(AnalyticsParams.KEY_TYPE, AnalyticsParams.LIKE)
                                    putString(
                                        AnalyticsParams.KEY_TITLE,
                                        holder.binding.root.context.subStringSafely(
                                            item.content?.answer,
                                            0,
                                            100
                                        )
                                    )
                                }
                            )
                        }
                        listener?.onClickGood(item)
                    }
                }
            }
            ivBad.setOnClickListener {
                when (item.isGood) {
                    null -> {
                        item.isGood = false
                        ivGood.setImageResource(R.drawable.ic_chat_good_n)
                        ivBad.setImageResource(R.drawable.ic_chat_bad)
                        if (!unlikeLoggedList.contains(item)) {
                            unlikeLoggedList.add(item)
                            AnalyticsEvents.AC_CHATAI_MSG_VOTE.logEvent(
                                Bundle().apply {
                                    putString(AnalyticsParams.KEY_TYPE, AnalyticsParams.DISLIKE)
                                    putString(
                                        AnalyticsParams.KEY_TITLE,
                                        holder.binding.root.context.subStringSafely(
                                            item.content?.answer,
                                            0,
                                            100
                                        )
                                    )
                                }
                            )
                        }
                        listener?.onClickBad(item)
                    }

                    true -> {
                        item.isGood = false
                        ivGood.setImageResource(R.drawable.ic_chat_good_n)
                        ivBad.setImageResource(R.drawable.ic_chat_bad)
                        if (!unlikeLoggedList.contains(item)) {
                            unlikeLoggedList.add(item)
                            AnalyticsEvents.AC_CHATAI_MSG_VOTE.logEvent(
                                Bundle().apply {
                                    putString(AnalyticsParams.KEY_TYPE, AnalyticsParams.DISLIKE)
                                    putString(
                                        AnalyticsParams.KEY_TITLE,
                                        holder.binding.root.context.subStringSafely(
                                            item.content?.answer,
                                            0,
                                            100
                                        )
                                    )
                                }
                            )
                        }
                        listener?.onClickBad(item)
                    }

                    false -> {
                        item.isGood = null
                        ivGood.setImageResource(R.drawable.ic_chat_good_n)
                        ivBad.setImageResource(R.drawable.ic_chat_bad_n)
                    }
                }
            }
            root.setOnLongClickListener {
                AnalyticsEvents.AC_CHATAI_COPY.logEvent(
                    Bundle().apply {
                        putString(AnalyticsParams.KEY_TYPE, AnalyticsParams.QUS)
                    }
                )
                listener?.onCopyContent(item)
                true
            }
        }
    }

    private fun bindLoadingViewHolder(holder: LoadingViewHolder, item: ChatItem) {
        //do nothing now
    }

    private fun bindErrorViewHolder(holder: ErrorViewHolder, item: ChatItem) {
        holder.binding.tvContent.text = item.content?.answer
    }

    private fun bindLimitsViewHolder(holder: LimitsViewHolder, item: ChatItem) {
        // 第一次绑定 limit 类型
        if (isFirstBindLimit) {
            isFirstBindLimit = false
            bindLimitsViewHolder(holder, item, mutableListOf<Any>().apply {
                add(Bundle().apply {
                    putBoolean(KEY_IS_LOADING, false)
                    putBoolean(KEY_IS_SHOW_AD_LIMITS, false)
                })
            })
            return
        }
        holder.binding.tvContent.setText(R.string.chat_remove_limits_ad_content)
        AnalyticsEvents.AC_CHATAI_FTG_SHOW.logEvent()
        holder.binding.subLimitItem.visibility = View.GONE
        holder.binding.ivArrow.isVisible = !item.isLoading
        holder.binding.progressbar.isVisible = item.isLoading
        holder.binding.adLimitsItem.run {
            visibility = View.VISIBLE
            post {
                if (!this@ChatRecyclerAdapter::animatorSet.isInitialized) {
                    animatorSet = AnimationUtil.startShakeAndFlashAnimation(
                        holder.itemView.context,
                        this,
                        holder.binding.lightIv
                    )
                }
                animatorSet.start()
            }
            setOnClickListener {
                notifyLimitsItemChanged(showAdLimits = true, isLoading = true)
                AnalyticsEvents.AC_CHATAI_FTG_CLICK.logEvent()
                listener?.onRemoveLimitsShow(false, isShowAdLimit = true)
            }
        }
    }

    private fun bindLimitsViewHolder(
        holder: LimitsViewHolder,
        item: ChatItem,
        payloads: MutableList<Any>
    ) {
        if (payloads.isNotEmpty()) {
            val payload = payloads[0] as? Bundle ?: return
            val isShowAdLimits = payload.getBoolean(KEY_IS_SHOW_AD_LIMITS)
            val isLoading = payload.getBoolean(KEY_IS_LOADING)
            val content =
                if (isShowAdLimits) R.string.chat_remove_limits_ad_content else R.string.chat_remove_limits_sub_content
            holder.binding.tvContent.setText(content)
            if (isShowAdLimits) {
                AnalyticsEvents.AC_CHATAI_FTG_SHOW.logEvent()
                holder.binding.subLimitItem.visibility = View.GONE
                holder.binding.adLimitsItem.run {
                    visibility = View.VISIBLE
                    post {
                        if (!this@ChatRecyclerAdapter::animatorSet.isInitialized) {
                            animatorSet = AnimationUtil.startShakeAndFlashAnimation(
                                holder.itemView.context,
                                this,
                                holder.binding.lightIv
                            )
                        }
                        animatorSet.start()
                    }
                    setOnClickListener {
                        notifyLimitsItemChanged(showAdLimits = true, isLoading = true)
                        AnalyticsEvents.AC_CHATAI_FTG_CLICK.logEvent()
                        listener?.onRemoveLimitsShow(false, isShowAdLimit = true)
                    }
                }
            } else {
                AnalyticsEvents.AC_CHATAI_RMLIM_SHOW.logEvent()
                holder.binding.subLimitItem.visibility = View.VISIBLE
                holder.binding.adLimitsItem.visibility = View.GONE
            }
            holder.binding.ivArrow.isVisible = !isLoading
            holder.binding.progressbar.isVisible = isLoading
        }
    }

    private fun bindPhotoViewHolder(holder: PhotoViewHolder, item: ChatItem) {
        holder.binding.tvContent.text = item.content?.answer
        holder.binding.root.setOnLongClickListener {
            AnalyticsEvents.AC_CHATAI_COPY.logEvent(
                Bundle().apply {
                    putString(AnalyticsParams.KEY_TYPE, AnalyticsParams.ASK)
                }
            )
            listener?.onCopyContent(item)
            true
        }
        item.content?.imagePath?.let {
            val localDisplayMetrics = DisplayMetrics()

            (holder.binding.root.context as? Activity)?.windowManager?.defaultDisplay?.getMetrics(
                localDisplayMetrics
            )
            val screenWidth = localDisplayMetrics.widthPixels
            val maxHeight = 185.dp2px()
            val maxWidth = screenWidth - 60.dp2px() - 17.dp2px() - 17.dp2px()
            val file = File(it)
            if (!file.exists()) {
                return@let
            }
            val input =
                FileInputStream(file)
            val options = BitmapFactory.Options()
            options.inJustDecodeBounds = true
            BitmapFactory.decodeStream(input, null, options)
            input.close()
            val width = options.outWidth
            val height = options.outHeight
            val layoutParams = holder.binding.ivPhoto.layoutParams
            if (maxWidth / maxHeight > width / height) {
                //图片比较长，以最大高度作为标准
                layoutParams.height = maxHeight
                layoutParams.width = (width.toFloat() / height.toFloat() * maxHeight).toInt()
            } else {
                //图片比较宽，以最大宽度作为标准
                layoutParams.width = maxWidth
                layoutParams.height = (height.toFloat() / width.toFloat() * maxWidth).toInt()
            }
            holder.binding.ivPhoto.layoutParams = layoutParams
            Glide.with(holder.binding.root.context)
                .load(Uri.fromFile(file))
                .into(holder.binding.ivPhoto)
        }
    }

    override fun getItemViewType(position: Int): Int {
        return data[position].type.ordinal
    }

    override fun getItemCount(): Int {
        return data.size
    }

    companion object {
        private const val KEY_IS_LOADING = "key_is_loading"
        private const val KEY_IS_SHOW_AD_LIMITS = "key_is_show_ad_limits"
    }

    inner class GuideViewHolder(val binding: ItemChatAnswerBinding) :
        RecyclerView.ViewHolder(binding.root)

    inner class QuestionViewHolder(val binding: ItemChatQuestionBinding) :
        RecyclerView.ViewHolder(binding.root)

    inner class AnswerViewHolder(val binding: ItemChatAnswerBinding) :
        RecyclerView.ViewHolder(binding.root)

    inner class LoadingViewHolder(binding: ItemChatLoadingBinding) :
        RecyclerView.ViewHolder(binding.root)

    inner class ErrorViewHolder(val binding: ItemChatErrorBinding) :
        RecyclerView.ViewHolder(binding.root)

    inner class LimitsViewHolder(val binding: ItemChatLimitsBinding) :
        RecyclerView.ViewHolder(binding.root)

    inner class PhotoViewHolder(val binding: ItemChatPhotoBinding) :
        RecyclerView.ViewHolder(binding.root)

    interface ChatFunctionListener {
        fun onCopyContent(item: ChatItem)

        fun onRegenerateVisible(isVisible: Boolean)

        fun onRemoveLimitsShow(isAuto: Boolean, isShowAdLimit: Boolean)

        fun onGoingToBilling()

        fun onClickGood(item: ChatItem)

        fun onClickBad(item: ChatItem)

        fun onShareContent(item: ChatItem)
    }
}